package com.bawei.mall.product.service.impl;

import com.alibaba.fastjson.JSON;
import com.bawei.common.core.domain.R;
import com.bawei.common.core.es.EsIndex;
import com.bawei.common.core.exception.ServiceException;
import com.bawei.common.core.utils.DateUtils;
import com.bawei.common.core.utils.bean.BeanUtils;
import com.bawei.common.rabbit.domain.Message;
import com.bawei.common.rabbit.enums.QueueEnum;
import com.bawei.common.security.utils.SecurityUtils;
import com.bawei.mall.product.cache.ProductInfoCache;
import com.bawei.mall.product.domain.MallProductInfo;
import com.bawei.mall.product.domain.MallProductRuleInfo;
import com.bawei.mall.product.domain.MallProductSkuInfo;
import com.bawei.mall.product.domain.model.ProductModel;
import com.bawei.mall.product.domain.model.SkuModel;
import com.bawei.mall.product.domain.reponse.ProductDetailsResponse;
import com.bawei.mall.product.domain.reponse.ProductInfoResponse;
import com.bawei.mall.product.domain.request.ProductInfoRequest;
import com.bawei.mall.product.mapper.MallProductInfoMapper;
import com.bawei.mall.product.service.IMallProductInfoService;
import com.bawei.mall.product.service.IMallProductRuleInfoService;
import com.bawei.mall.product.service.IMallProductSkuInfoService;
import com.bawei.system.domain.vo.EsDocInsertVo;
import com.bawei.system.remote.api.RemoteEsDocService;
import com.bawei.system.remote.api.RemoteEsIndexService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 商品信息Service业务层处理
 *
 * @author DongZeLiang
 * @date 2022-09-19
 */
@Service
@Slf4j
public class MallProductInfoServiceImpl implements IMallProductInfoService {
    @Autowired
    private MallProductInfoMapper mallProductInfoMapper;

    @Autowired
    private IMallProductSkuInfoService skuInfoService;

    @Autowired
    private IMallProductRuleInfoService ruleInfoService;

    @Autowired
    private ProductInfoCache productInfoCache;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private RemoteEsDocService remoteEsDocService;

    @Autowired
    private RemoteEsIndexService remoteEsIndexService;


    /**
     * 项目启动时，把商品数据初始化到ES中
     */
    @PostConstruct
    public void init() {
        loadingProductInfoToEs();
    }

    /**
     * 查询商品信息
     *
     * @param id 商品信息主键
     * @return 商品信息
     */
    @Override
    public ProductInfoResponse selectMallProductInfoById(Long id) {
        MallProductInfo mallProductInfo = mallProductInfoMapper.selectMallProductInfoById(id);
        ProductInfoResponse productInfoResponse = new ProductInfoResponse();
        BeanUtils.copyBeanProp(productInfoResponse, mallProductInfo);
        productInfoResponse.setSkuInfoList(
                skuInfoService.selectMallProductSkuInfoList(new MallProductSkuInfo() {{
                    setProductId(id);
                }})
        );
        return productInfoResponse;
    }

    @Override
    public ProductDetailsResponse selectProductDetailsById(Long productId) {
        if (productId == null || productId == 0) {
            throw new ServiceException("查询商品信息，依据不合法！");
        }
        ProductDetailsResponse productDetailsResponse = new ProductDetailsResponse();
        ProductModel productModel = mallProductInfoMapper.selectProductModelById(productId);
        if (productModel == null) {
            throw new ServiceException("查询商品信息，商品数据为空");
        }
        productDetailsResponse.setProduct(productModel);
        List<MallProductSkuInfo> mallProductSkuInfos = skuInfoService.selectMallProductSkuInfoList(productId);
        if (mallProductSkuInfos == null || mallProductSkuInfos.size() == 0) {
            throw new ServiceException("查询商品信息，SKU数据为空");
        }
        productDetailsResponse.setSkuList(mallProductSkuInfos);
        MallProductRuleInfo ruleInfo = ruleInfoService.selectMallProductRuleInfoById(productModel.getRuleId());
        if (ruleInfo == null) {
            throw new ServiceException("查询商品信息，规格数据为空");
        }
        productDetailsResponse.setProductRule(ruleInfo);
        return productDetailsResponse;
    }

    /**
     * 查询商品信息列表
     *
     * @param mallProductInfo 商品信息
     * @return 商品信息
     */
    @Override
    public List<MallProductInfo> selectMallProductInfoList(MallProductInfo mallProductInfo) {
        return mallProductInfoMapper.selectMallProductInfoList(mallProductInfo);
    }

    /**
     * 新增商品信息
     *
     * @param productInfoRequest 商品信息
     * @return 结果
     */
    @Override
    @Transactional
    public int insertMallProductInfo(ProductInfoRequest productInfoRequest) {
        productInfoRequest.setCreateBy(String.valueOf(SecurityUtils.getUserId()));
        productInfoRequest.setCreateTime(DateUtils.getNowDate());
        int i = mallProductInfoMapper.insertMallProductInfo(productInfoRequest);
        if (i == 0) {
            return i;
        }

        skuInfoService.batchInsertProductSku(
                SkuModel.builderSkuModel(productInfoRequest.getId(), productInfoRequest.getSkuInfoList())
        );

        // 给搜索系统发送消息需要进行搜索更新
        try {
            rabbitTemplate.convertAndSend(QueueEnum.PRODUCT_ADD.queueName(),
                    Message.builderMsg(productInfoRequest.getId()));
        } catch (ServiceException serviceException) {
            throw new ServiceException("给搜索系统发送消息需要进行搜索更新失败！");
        }
        return i;
    }

    /**
     * 修改商品信息
     *
     * @param productInfoRequest 商品信息
     * @return 结果
     */
    @Override
    @Transactional
    public int updateMallProductInfo(ProductInfoRequest productInfoRequest) {
        productInfoRequest.setUpdateBy(String.valueOf(SecurityUtils.getUserId()));
        productInfoRequest.setUpdateTime(DateUtils.getNowDate());
        int i = mallProductInfoMapper.updateMallProductInfo(productInfoRequest);
        if (i == 0) {
            //将商品信息推送至MQ，异步更新ES
            try {
                rabbitTemplate.convertAndSend(QueueEnum.PRODUCT_ADD.queueName(),
                        Message.builderMsg(productInfoRequest.getId()));
            } catch (ServiceException serviceException) {
                throw new ServiceException("给搜索系统发送消息需要进行搜索更新失败！");
            }
            return i;
        }
        skuInfoService.deleteMallProductSkuInfoByProductId(productInfoRequest.getId());
        skuInfoService.batchInsertProductSku(
                SkuModel.builderSkuModel(productInfoRequest.getId(), productInfoRequest.getSkuInfoList())
        );
        return i;
    }

    /**
     * 批量删除商品信息
     *
     * @param ids 需要删除的商品信息主键
     * @return 结果
     */
    @Override
    public int deleteMallProductInfoByIds(Long[] ids) {
        skuInfoService.deleteMallProductSkuInfoByProductIds(ids);
        for (Long id : ids) {
            // 延迟执行
            productInfoCache.delayRemove(id);
        }
        return mallProductInfoMapper.deleteMallProductInfoByIds(ids);
    }

    /**
     * 删除商品信息信息
     *
     * @param id 商品信息主键
     * @return 结果
     */
    @Override
    public int deleteMallProductInfoById(Long id) {
        return mallProductInfoMapper.deleteMallProductInfoById(id);
    }

    /**
     * 商品总条数
     *
     * @param mallProductInfo 商品查询
     * @return
     */
    @Override
    public Long selectMallProductInfoCount(MallProductInfo mallProductInfo) {
        return mallProductInfoMapper.selectMallProductInfoCount(mallProductInfo);
    }

    /**
     * 商品上下架
     *
     * @param id
     * @param isUpload
     */
    @Override
    @Transactional(rollbackFor = Exception.class) // 指定对所有异常都回滚
    public void uploadInfo(Long id, boolean isUpload) throws RuntimeException{
        //参数校验
        if(id ==null){
            throw new ServiceException("商品id不能为空！");
        }
        //修改上架下架状态
        if(isUpload){
            //上架
            mallProductInfoMapper.updateInfo(id,1);
            //查询商品spu信息
            MallProductInfo mallProductInfo = mallProductInfoMapper.selectMallProductInfoById(id);
            if (mallProductInfo == null) {
                throw new ServiceException("商品信息不存在");
            }
            //查询skuInfo信息
            List<MallProductSkuInfo> mallProductSkuInfos = skuInfoService.selectMallProductSkuInfoList(id);
            if(CollectionUtils.isEmpty(mallProductSkuInfos)){
                throw new ServiceException("商品id:"+id+"下不存在sku信息！");
            }
            //批量添加sku
            List<EsDocInsertVo> esDocInsertVo=taansFormData(mallProductInfo,mallProductSkuInfos);
            try {
                remoteEsDocService.batchInsertDocs(esDocInsertVo);
            } catch (Exception e) {
                // 如果batchInsertDocs操作失败，则抛出运行时异常以触发回滚
                throw new RuntimeException("Failed to upload document to Elasticsearch", e);
            }
        }else{
            //下架
            //参数校验
            if(id!=null){
                //修改SPU表下架状态
                mallProductInfoMapper.updateInfo(id,3);
                //根据spuid查询出所有的skuid
                List<MallProductSkuInfo> list = skuInfoService.selectMallProductSkuInfoList(id);
                List<String> ids = list.stream()
                        .map(MallProductSkuInfo::getId) // 假设getId()是获取MallProductSkuInfo中id的方法
                        .map(Object::toString) // 或者使用 Long::toString 更具体一些
                        .collect(Collectors.toList());
                //远程调用es完成删除操作
                remoteEsDocService.deleteId(ids,EsIndex.PRODUCT_INFO);
            }
        }
    }

    private List<EsDocInsertVo> taansFormData(MallProductInfo mallProductInfo, List<MallProductSkuInfo> mallProductSkuInfos) {
        //构建返回的结果集
        List<EsDocInsertVo> esDocInsertVos = new ArrayList<>();
        mallProductSkuInfos.forEach(mallProductSkuInfo -> {
            EsDocInsertVo esDocInsertVo = new EsDocInsertVo();
            //es主键id
            esDocInsertVo.setId(String.valueOf(mallProductSkuInfo.getId()));
            //可以定义为常量
            esDocInsertVo.setIndexName(EsIndex.PRODUCT_INFO);
            //默认为_doc
            esDocInsertVo.setTypeName("_doc");
            //TODO待补全data
            // 创建一个新的 Map 来存储数据
            Map<String, Object> dataMap = new HashMap<>();

            //以sku信息为主体，补全相关的spu信息
            //skuid
            dataMap.put("skuId",mallProductSkuInfo.getId());
            //商品表id
            dataMap.put("spuId", mallProductSkuInfo.getProductId());
            //商品表名称
            dataMap.put("name",mallProductInfo.getName());
            //商品标题、描述、关键字
            List<String> list = new ArrayList<>();
            list.add(mallProductInfo.getName());
            list.add(mallProductInfo.getProductDesc());
            list.add(mallProductInfo.getKeywords());
            list.add("手机");
            list.add("小米");
            list.add("小孩玩具");
            list.add("手动螺丝刀");
            list.add("手提包");
            list.add("手动汽车");
            list.add("华子");
            list.add("小米汽车");
            list.add("小米电脑");
            list.add("小米笔记本");
            dataMap.put("titleSuggest",list);
            //sku信息
            dataMap.put("sku", mallProductSkuInfo.getSku());
            //商品库存
            dataMap.put("stock", mallProductSkuInfo.getStock());
            //商品价格
            dataMap.put("price", mallProductSkuInfo.getPrice());
            //关键字
            dataMap.put("keyWords", mallProductInfo.getKeywords());
            //进价
            dataMap.put("purchasePrice", mallProductSkuInfo.getPurchasePrice());
            //售价
            dataMap.put("sellingPrice", mallProductSkuInfo.getSellingPrice());
            //完成商品图片集的保存与查询
            List<String> listpics = new ArrayList<>();
            listpics.add(mallProductInfo.getCarouselImages());
            listpics.add(mallProductInfo.getImg());
            dataMap.put("image", listpics);
            //编号
            dataMap.put("number", mallProductSkuInfo.getNumber());
            //创建时间
            dataMap.put("createTime", mallProductInfo.getCreateTime());
            //重量
            dataMap.put("weight", mallProductSkuInfo.getWeight());
            //体积
            dataMap.put("volume", mallProductSkuInfo.getVolume());
            //乐观锁
            dataMap.put("revision", mallProductSkuInfo.getRevision());
            //完成相关字典值的转换
            // 创建一个Map来存储状态码和对应的文字描述
            Map<Integer, String> upstateMap = new HashMap<>();
            upstateMap.put(0, "未上架");
            upstateMap.put(1, "已上架");
            upstateMap.put(2, "上架失败");
            upstateMap.put(3, "已下架");
            Long upstatesLong = mallProductInfo.getUpstates();
            Integer upstates = upstatesLong.intValue();
            String upstateText = upstateMap.getOrDefault(upstates, "未知状态");
            dataMap.put("upstates", upstateText);
            esDocInsertVo.setData(dataMap);
            esDocInsertVos.add(esDocInsertVo);
        });
        return esDocInsertVos;
    }


    @Override
    public void loadingProductInfoToEs() {
        //查询所有商品信息
        List<MallProductInfo> mallProductInfos = mallProductInfoMapper.selectMallProductInfoList(new MallProductInfo());
        if (mallProductInfos == null || mallProductInfos.size() == 0) {
            log.info("暂无需要同步的商品");
        }
        //调用ES查询索引是否存在
        R<Boolean> indexExit = remoteEsIndexService.indexExit("mall_product");
        if (!indexExit.getData()) {
            log.info("mall_product索引不存在,调用ES服务创建索引");
            //创建索引
            R<Boolean> indexCreate = remoteEsIndexService.indexCreate("mall_product");
            if (!indexCreate.getData()) {
                log.info("创建mall_product索引失败");
            }
            //批量同步商品信息到ES
            //构建参数
            List<EsDocInsertVo> esDocInsertVo = builderProductInfoToEs(mallProductInfos);
            //调用ES服务批量插入文档
            R<Boolean> batchInsert = remoteEsDocService.batchInsertDocs(esDocInsertVo);
            if (batchInsert.getData()) {
                log.info("批量同步商品信息到ES成功");
            }

        }

    }

    private List<EsDocInsertVo> builderProductInfoToEs(List<MallProductInfo> mallProductInfos) {
        List<EsDocInsertVo> esDocInsertVos = new ArrayList<>();
        mallProductInfos.stream().forEach(mallProductInfo -> {
            EsDocInsertVo esDocInsertVo = new EsDocInsertVo();
            esDocInsertVo.setId(String.valueOf(mallProductInfo.getId()));
            esDocInsertVo.setIndexName("mall_product");
            //对象转为Map
            Map<String, Object> data = JSON.parseObject(JSON.toJSONString(mallProductInfo), Map.class);
            esDocInsertVo.setData(data);
            esDocInsertVos.add(esDocInsertVo);
        });
        return esDocInsertVos;
    }
}
